home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / updates / update21.zoo / lib / realloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-03  |  2.1 KB  |  95 lines

  1. /* from the TOS GCC library */
  2. /* malloc, free, realloc: dynamic memory allocation */
  3. /* 5/2/92 sb -- modified for Heat-n-Serve C to accomodate its 16-bit size_t */
  4. /* 5/5/92 sb -- realloc() gets its own file to reduce library drag */
  5.  
  6. #include <stddef.h>    /* for size_t */
  7. #include <stdlib.h>
  8. #include <memory.h>
  9. #include <string.h>
  10. #include <assert.h>
  11. #include <unistd.h>
  12. #include "lib.h"
  13.  
  14. __EXTERN void *_malloc __PROTO((unsigned long));
  15. __EXTERN void _bzero __PROTO((void *, unsigned long));
  16.  
  17. #ifdef __GNUC__
  18. asm(".stabs \"_realloc\",5,0,0,__realloc"); /* dept of clean tricks */
  19. #endif
  20.  
  21. void * _realloc(_r, n)
  22. void *_r;
  23. unsigned long n;
  24. {
  25.   struct mem_chunk *p, *q, *r = (struct mem_chunk *) _r;
  26.   long sz;
  27.  
  28. /* obscure features: realloc(NULL,n) is the same as malloc(n)
  29.  *               realloc(p, 0) is the same as free(p)
  30.  */
  31.   if (!r)
  32.     return _malloc(n);
  33.   if (n == 0) {
  34.     free(_r);
  35.     return NULL;
  36.   }
  37.   p = r - 1;
  38.   sz = (n + sizeof(struct mem_chunk) + 7) & ~7;
  39.  
  40.   if (p->size > sz) 
  41.     {            /* block too big, split in two */
  42.     q = (struct mem_chunk * )(((long) p) + sz);
  43.     q->size = p->size - sz;
  44.         q->valid = VAL_ALLOC;
  45.     free(q + 1);
  46.     p->size = sz;
  47.     }
  48.     else 
  49.   if (p->size < sz)
  50.     {            /* block too small, get new one */
  51.     struct mem_chunk *s, *t;
  52.     q = &_mchunk_free_list;
  53.     t = _mchunk_free_list.next;
  54.     while (t != NULL && t < p)
  55.       {
  56.       q = t;
  57.       t = t->next;
  58.       }
  59.  
  60.     /* merge after if possible */
  61.     s = (struct mem_chunk * )(((long) p) + p->size);
  62.     if (t != NULL && s >= t && p->size + t->size >= sz)
  63.       {
  64.       assert(s == t);
  65.       p->size += t->size;
  66.       q->next = t->next;
  67.       t->size = 0;
  68.       t->next = NULL;
  69.       }
  70.     else
  71.       {
  72.       q = (struct mem_chunk * )_malloc(n);
  73.       if (q != NULL)
  74.     {
  75.     n = p->size - sizeof(struct mem_chunk);
  76.     _bcopy(r, q, n);
  77.         free(r);    /* free r only if we got a new block */
  78.         }
  79.       /* else we could try to mlalloc the rest and hope that we can merge */
  80.       r = q;
  81.     }
  82.   }
  83.   /* else current block will do just fine */
  84.   return((void * )r);
  85. }
  86.  
  87. #ifndef __GNUC__
  88. void * realloc(_r, n)
  89. void *_r;
  90. size_t n;
  91. {
  92.   return _realloc(_r, (unsigned long) n);
  93. }
  94. #endif
  95.